import asyncio
import time
from pathlib import Path
from typing import Any, List
from uuid import uuid4

from sqlalchemy import select, insert
from sqlalchemy.ext.asyncio.session import AsyncSession

from app.models import User, Role, UserRole, Menu, RoleMenu, Region, Api, Dict, DictType
from app.models.base import IdType
from app.utils.file import load_file_data


async def async_init_seed_data(session: AsyncSession) -> bool:
    async with session.begin():
        # 检测是否有数据
        existing = await session.execute(select(User.id).limit(1))
        if existing.scalars().first():
            print("{0:-^100}".format("种子数据初始化结果：存在数据，已跳过"))
            return False
        print("{0:-^100}".format("种子数据初始化开始"))
        # 并行加载数据
        (
            user_data,
            role_data,
            menu_data,
            user_role_data,
            role_menu_data,
            dict_type_data,
            dict_data,
            region_data,
            api_data,
        ) = await asyncio.gather(
            load_data("user.json"),
            load_data("role.json"),
            load_data("menu.json"),
            load_data("user_role.json"),
            load_data("role_menu.json"),
            load_data("dict_type.json"),
            load_data("dict.json"),
            load_data("region.json"),
            load_data("api.json"),
        )

        try:
            start_time = time.time()
            await session.execute(insert(User.__table__), user_data)
            await session.execute(insert(Role.__table__), role_data)
            await session.execute(insert(Menu.__table__), menu_data)
            await session.execute(insert(UserRole.__table__), user_role_data)
            await session.execute(insert(RoleMenu.__table__), role_menu_data)
            await session.execute(insert(DictType.__table__), dict_type_data)
            await session.execute(insert(Dict.__table__), dict_data)

            top_level_apis  = [item for item in api_data if item.get("parent_id") is None]
            child_apis = [item for item in api_data if item.get("parent_id") is not None]

            await session.execute(insert(Api.__table__), top_level_apis)
            await session.execute(insert(Api.__table__), child_apis )

            top_level_regions  = [item for item in region_data if item.get("parent_id") is None]
            child_regions = [item for item in region_data if item.get("parent_id") is not None]

            await session.execute(insert(Region.__table__), top_level_regions)
            await session.execute(insert(Region.__table__), child_regions)

            await session.commit()
            print("{0:-^100}".format("种子数据初始化结果：成功"))
            print(
                "{0:-^100}".format(
                    f"种子数据初始化执行耗时：{time.time() - start_time}"
                )
            )
            return True
        except Exception as e:
            await session.rollback()
            print("{0:-^100}".format(f"种子数据初始化结果"))
            print(f"失败：{str(e)}")
        finally:
            # 4. 确保会话关闭
            await session.close()
        return False


async def format_data(tree_list: List, parent_id: IdType = None):
    flat_list = []
    for item in tree_list:
        id = uuid4()
        # 创建新对象并处理ID
        new_obj = item.copy()
        # 添加 id 属性
        # 添加 parent_id 属性，如果 parent_id 存在
        if "id" not in item:
            new_obj["id"] = id
            if parent_id is not None:
                new_obj["parent_id"] = parent_id

        # 如果新对象里面还存在 children 属性，则删除这个属性
        if "children" in new_obj:
            del new_obj["children"]

        # 如果所有关于id的值类型不是UUID类型，则转换
        for key, value in new_obj.items():
            if key.endswith("_id") or key == "id":
                if new_obj[key] and type(new_obj[key]) is not IdType:
                    new_obj[key] = IdType(new_obj[key])

        # 将新对象添加到列表
        flat_list.append(new_obj)

        # 如果存在自身循环引用的 children 属性，则递归处理
        if "children" in item:
            flat_list.extend(await format_data(item["children"], id))

    return flat_list


async def load_data(data_file: str, data_dri: Path = Path("static/init_data")) -> list[dict[str, Any]]:
    data = load_file_data(data_file, data_dri)
    result = await format_data(data)
    return result
